import java.io.*;
import java.net.*;
//import java.awt.*;
//import java.awt.event.ActionEvent;
//import java.awt.event.ActionListener;
import java.util.*;


public class Terminal {

        final int connReady = 0;
        int openPorts = 2011;
       
       
        int listeningPort = 0;
       
        public ArrayList<ChatSession> sessionList;
        ConnectionListener connListener;
       
        public Terminal () {

                sessionList = new ArrayList<ChatSession>();
               
        }
       
        public void startListener( int port ) {

                listeningPort = port;
               
                try {
                        connListener = new ConnectionListener( this, listeningPort );
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
               
                System.out.println("Terminal: connListener.start();");
                connListener.start();
        }
       
        public void connectTo(InetAddress address, int port ) {
               
                int ourPort = 0;        
                int theirPort = 0;
                Socket requestSocket = null;
                Socket sessionSocket = null;
                ServerSocket setupSocket = null;
               
                BufferedReader reader = null;
                BufferedWriter writer = null;
               
               
                String replyBuffer = null;
                boolean sessionReady = false;

                int SID = 0;
               
                // TODO: Setup time-sensitive failure
                try {
                       
                        System.out.println("Terminal: connecting to " + address.getHostAddress() +":" + port );
                       
                        //TODO: retry error handling here
                        requestSocket = new Socket( address, port);
                       
                        System.out.println( "Terminal - requestSocket raddr=" + requestSocket.getInetAddress().getHostAddress()
                                                                + " rport=" + requestSocket.getPort()
                                                                + " FROM lport="+ requestSocket.getLocalPort());
                       
                        setupSocket = new ServerSocket( 0, 1 );
                        ourPort = setupSocket.getLocalPort();
                       
                        writer = new BufferedWriter(new OutputStreamWriter(requestSocket.getOutputStream()) );
                       

                        writer.write("REQUEST port=" + ourPort );
                        writer.newLine();
                        writer.flush();
                               
                        System.out.println("Terminal - sending request: REQUEST port=" + ourPort );
                               
                        System.out.println("Terminal - waiting for " + requestSocket.getInetAddress().getHostAddress()
                                                                + " to connect to port " + ourPort );

                        requestSocket.close();
                       
                } catch (IOException e) {
                        System.out.println("failed to connect to " + address.getHostAddress() + ":" + port);
                        e.printStackTrace();
                        return;
                }

                //TODO: add time-out logic here, you can do setupSocket.setSoTimeout(timeout) but need to catch SocketTimeoutException
                try {
                        sessionSocket = setupSocket.accept();
                } catch (IOException e ) {
                        System.out.println("no action from " + address.getHostAddress() );
                        e.printStackTrace();
                        return;
                }


               
                try {

                        // TODO: should check if the socket accepted the same address as before
                        setupSocket.close();
                       
                        reader = new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()) );

                        /*
                    StringTokenizer tokens = new StringTokenizer(replyBuffer);
                    String reply_type_string = tokens.nextToken();

                    String[] fieldAndValue = new String[2];
                    */
                       
                        // System.out.println("Terminal - connectTo(): parsing message");
                       
                        replyBuffer = reader.readLine();
                       
                        if( replyBuffer != null ) {
                                System.out.println("Terminal - got reply: " + replyBuffer);
                        }
                       
                    // parse for their port info
                    // OKAY port=%d

                    String[] fieldAndValue = new String[2];
                       
                    StringTokenizer tokens = new StringTokenizer(replyBuffer);
                    String reply_type_string = null;
                   
                    // TODO: better message parsing
                    // TODO: timeout and rejection logic
                while ( tokens.hasMoreElements() ) {
                       
                        reply_type_string = tokens.nextToken();
                        fieldAndValue = reply_type_string.split( "=" );
                       
                        if( fieldAndValue[0].compareTo("port") == 0 ) {
                                theirPort = Integer.parseInt(fieldAndValue[1]);
                        }
                       
                }

                    ourPort = sessionSocket.getLocalPort();
               
                    SID = ourPort;
                        sessionReady = true;

                } catch (Exception e) {
                        System.out.println("fail to establish connection " + address.getHostAddress() + ":" + port);
                        e.printStackTrace();
                }
               
                if( sessionReady ) {
                        System.out.println("Terminal - sesssion established");
                        System.out.println("Terminal - sessionSocket: raddr=" + sessionSocket.getInetAddress().getHostName()
                                        +" rport=" + sessionSocket.getPort()
                                        + " lport="+ sessionSocket.getLocalPort());
                       
                        createSession( sessionSocket , SID );
                }
                else {
                        System.out.println("connection denied or timeout");
                }
           
        }
       
        public void createSession( Socket connSocket, int SID ) {
                ChatSession newSession = new ChatSession( connSocket, SID);
                sessionList.add(newSession);
               

                // Start Session GUI
        }
       
        void killSession( int SessionID ) {
               
        }
       

}

